#ifndef CAccesCourrierH
#define CAccesCourrierH
//---------------------------------------------------------------------------
#include "Outils.h"
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include "CCourrier.h"  //Pour le type GetValueOfVarEvent
#include "uListeLangues.h" //Pour IDLangue
//---------------------------------------------------------------------------
struct TMiseEnPage
{
  int PositionEnTete;
  int PositionPiedDePage;
  int MargeHaut;
  int MargeBas;
  int MargeDroite;
  int MargeGauche;
};

struct TDescriptifModele
   {
   AnsiString aLogiciel;
   AnsiString aCategorie;
   AnsiString aLibelle;
   short shValParam1;
   short shValParam2;
   bool bIsModeleUtilisateur;
   };

struct TDescriptifModeleRenomme
   {
   AnsiString aLogiciel;
   AnsiString aCategorie;
   AnsiString aAncienLibelle;
   AnsiString aNouveauLibelle;
   short shValParam1;
   short shValParam2;
   bool bIsModeleUtilisateur;
   };

class tMaillonListeCourrier
   {
   public :
      TDescriptifModele sDescriptifModele;
      tMaillonListeCourrier *MaillonSuiv;

   public : // La suite ne concerne pas les programmeurs externes
      __fastcall tMaillonListeCourrier() {MaillonSuiv = NULL;};
   };

class tMaillonNo
   {
   public :
      unsigned long NoCoord;
      tMaillonNo *MaillonSuiv;

   public : // La suite ne concerne pas les programmeurs externes
      __fastcall tMaillonNo() {NoCoord = 0 ; MaillonSuiv = NULL;};
   };

enum TTypeTblCour
   {
   eTBL_COUR_MODELES, //Pour tester la présence des modèles
   eTBL_COUR_VAR,     //Pour tester la présence des variables
   };

typedef bool (*FctMigrerTables)(void);

typedef tMaillonListeCourrier* (*FctListeModeles)(const AnsiString &aLogiciel, const AnsiString &aCategorie);

typedef bool (*FctGenererFichiersCourrier)(const AnsiString &aLogiciel,
                                           const AnsiString &aCategorie,
                                           const AnsiString &aLibelle,
                                           IDLangue eLangue,
                                           IDOrientation eOrientation,
                                           unsigned long NoCoord,
                                           TStringList *ListeFichiers,
                                           GetValueOfVarEvent FonctionGetValueOfVar,
                                           TMiseEnPage *rMarges,
                                           const AnsiString &aRepSecondaire,
                                           eNivModele eNoModeleSecondaire);

typedef bool (*FctTexteModeleExists)(const AnsiString &aLogiciel,
                                     const AnsiString &aCategorie,
                                     const AnsiString &aLibelle,
                                     IDLangue eLangue,
                                     IDOrientation eOrientation);

typedef bool (*FctVerifierModele)(const AnsiString &aFichier, const AnsiString &aLogiciel,
                                  const AnsiString &aCategorie, const AnsiString &aLibelle,
                                  IDLangue eLangue,
                                  IDOrientation eOrientation,
                                  short shParam1, short shParam2);

typedef bool (*FctImporterModele)(const AnsiString &aFichier,
                                  bool bRemplacer,
                                  const AnsiString &aLogiciel,
                                  const AnsiString &aCategorie,
                                  const AnsiString &aLibelle,
                                  IDLangue eLangue,
                                  IDOrientation eOrientation,
                                  short shParam1,
                                  short shParam2);

typedef bool (*FctImporterModeleSecondaire)(const AnsiString &aFichier,
                                            bool bRemplacer,
                                            const AnsiString &aLogiciel,
                                            const AnsiString &aCategorie,
                                            const AnsiString &aLibelle,
                                            IDLangue eLangue,
                                            IDOrientation eOrientation,
                                            const AnsiString &aRepSecondaire,
                                            eNivModele eNoModeleSecondaire
                                            );

typedef bool (*FctInstallerModele)(const AnsiString &aFichier,
                                   const AnsiString &aLogiciel,
                                   const AnsiString &aCategorie,
                                   const AnsiString &aLibelle,
                                   IDLangue eLangue,
                                   IDOrientation eOrientation,
                                   short shParam1,
                                   short shParam2);

typedef bool (*FctCreerModeleSecondaire)(const AnsiString &aLogiciel,
                                         const AnsiString &aCategorie,
                                         const AnsiString &aLibelle,
                                         IDLangue eLangue,
                                         IDOrientation eOrientation,
                                         const AnsiString &aRepSecondaire,
                                         eNivModele eNoModeleSource,
                                         eNivModele eNoModeleCible
                                         );

typedef bool (*FctVerifierVariable)(const AnsiString &aLogiciel, const AnsiString &aCategorie,
                                    const AnsiString &aNom, const AnsiString &aLibelle,
                                    const AnsiString &aValeur, bool bIsModifiableParUtilisateur);

typedef bool (*FctSupprimerVariable)(const AnsiString &aLogiciel, const AnsiString &aCategorie,
                                     const AnsiString &aLibelle);

typedef unsigned long (*FctIniCoordParDefaut)(unsigned long NumEmet, tMaillonNo *lstDest,
                                              const AnsiString &aLogiciel, const AnsiString &aCategorie,
                                              const AnsiString &aLibelle, unsigned long NoCoord);

typedef unsigned long (*FctCompleteCoordParDefaut)(unsigned long NumEmet, tMaillonNo *lstDest,
                                                   const AnsiString &aLogiciel, const AnsiString &aCategorie,
                                                   const AnsiString &aLibelle, unsigned long NoCoord);

typedef bool (*FctGetListeEmetDest)(const AnsiString &aLogicielCourrier,
                                    const AnsiString &aCategorieCourrier,
                                    const AnsiString &aLibelle, unsigned long NoCoord,
                                    unsigned long *pNumEmetteur, tMaillonNo *lstDestinataires);
typedef bool (*FctGetDescriptifModele)(const AnsiString &aLogiciel,
                                       const AnsiString &aCategorie,
                                       const AnsiString &aLibelle,
                                       TDescriptifModele *sDescriptifModele);

typedef bool (*FctRenommerModele)(const AnsiString &aOldLogiciel,
                                  const AnsiString &aOldCategorie,
                                  const AnsiString &aOldLibelle,
                                  AnsiString aNewLogiciel,
                                  AnsiString aNewCategorie,
                                  AnsiString aNewLibelle);
typedef bool (*FctSupprimerModele)(const AnsiString &aLogiciel,
                                   const AnsiString &aCategorie,
                                   const AnsiString &aLibelle);

typedef bool (*FctModifierModele) (const AnsiString &aLogiciel,
                                   const AnsiString &aCategorie,
                                   const AnsiString &aCategorieVariables,
                                   const AnsiString &aLibelle,
                                   IDLangue eLangue,
                                   IDOrientation eOrientation,
                                   bool bGererEnTeteEtPiedDePage,
                                   const AnsiString &aRepSecondaire,
                                   eNivModele eNoModeleSecondaire,
                                   const TContrainteTaille *sContrainteTaille
                                   );

typedef void (*FctSupprimerModelesSecondaire)(const AnsiString &aLogiciel,
                                              const AnsiString &aCategorie,
                                              const AnsiString &aLibelle,
                                              IDLangue eLangue,
                                              IDOrientation eOrientation,
                                              const AnsiString &aRepSecondaire,
                                              eNivModele eNoModeleSecondaire);
typedef bool (*FctDonneesSontTrouveesDansTable) (TTypeTblCour eTypeTable,
                                                 const AnsiString &aLogiciel);

typedef AnsiString (*FctGetNomFichier)(const AnsiString &aLogiciel,
                                       const AnsiString &aCategorie,
                                       const AnsiString &aLibelle,
                                       IDLangue eLangue,
                                       IDOrientation eOrientation,
                                       const AnsiString &aRepSecondaire,
                                       eNivModele eNoModeleSecondaire
                                       );

typedef bool (*FctGetInfosFichierModele)(const AnsiString &aCourrier,
                                         AnsiString *aLogiciel,
                                         AnsiString *aCategorie,
                                         AnsiString *aLibelle,
                                         IDLangue *eLangue,
                                         IDOrientation *eOrientation);

typedef void (*FctEnregistrerModReq)(short shIDUser,
                                     const AnsiString &aLogiciel,
                                     const AnsiString &aCategorie,
                                     const AnsiString &aLibelle,
                                     const AnsiString &aRepDossier);

class PACKAGE_OUTILS CAccesCourrier : public TComponent
{
private:
   HANDLE hEditeur;
   AnsiString aFileNameEicEdito;

   FctMigrerTables _MigrerTables;
   FctTexteModeleExists _TexteModeleExists;
   FctVerifierModele _VerifierModele;
   FctImporterModele _ImporterModele;
   FctImporterModeleSecondaire _ImporterModeleSecondaire;
   FctInstallerModele _InstallerModele;
   FctCreerModeleSecondaire _CreerModeleSecondaire;
   FctVerifierVariable _VerifierVariable;
   FctSupprimerVariable _SupprimerVariable;
   FctIniCoordParDefaut _IniCoordParDefaut;
   FctCompleteCoordParDefaut _CompleteCoordParDefaut;
   FctGetListeEmetDest _GetListeEmetDest;
   FctRenommerModele _RenommerModele;
   FctSupprimerModele _SupprimerModele;
   FctSupprimerModelesSecondaire _SupprimerModelesSecondaire;
   FctModifierModele _ModifierModele;
   FctDonneesSontTrouveesDansTable _DonneesSontTrouveesDansTable;
   FctGetNomFichier _GetNomFichier;
   FctGetDescriptifModele _GetDescriptifModele;
   FctEnregistrerModReq _EnregistrerModReq;

   unsigned long nNoCoord;

public:
  __fastcall CAccesCourrier(TComponent* Owner);
  virtual __fastcall ~CAccesCourrier();
  bool __fastcall MigrerTables();

  /// Exemple d'utilisation des fonctions ListeModelesEditeur et AnsiStringToTDescriptifModele
  //////////////////////////////////////////////////////////////////////////////
  // TStringList *ListeDesCourriers = new TStringList;
  // TDescriptifModele sDescriptifModele;
  // if(CAccesCourrier1->ListeModelesEditeur("CO", "", ListeDesCourriers))
  //    for (int i=0 ; i<ListeDesCourriers->Count ; i++)
  //       CAccesCourrier1->AnsiStringToTDescriptifModele(ListeDesCourriers->Strings[i], &sDescriptifModele);
  // delete ListeDesCourriers;
  //////////////////////////////////////////////////////////////////////////////
  bool __fastcall ListeModelesEditeur(const AnsiString &aLogiciel,
                                      const AnsiString &aCategorie,
                                      TStringList *slListeDesModeles);
  void __fastcall AnsiStringToTDescriptifModele(const AnsiString &aChaineDescriptive, TDescriptifModele *sDescriptifModele) const;

  bool GetDescriptifModele(const AnsiString &aLogiciel,
                           const AnsiString &aCategorie,
                           const AnsiString &aLibelle,
                           TDescriptifModele *sDescriptifModele);

  bool __fastcall GenererFichiersCourrier(const AnsiString &aLogiciel,
                                          const AnsiString &aCategorie,
                                          const AnsiString &aLibelle,
                                          IDLangue eLangue,
                                          IDOrientation eOrientation,
                                          unsigned long NoCoord,
                                          TStringList *ListeFichiers,
                                          GetValueOfVarEvent FonctionGetValueOfVar,
                                          TMiseEnPage *Rect,
                                          const AnsiString &aRepSecondaire = EmptyStr,
                                          eNivModele shNoModeleSecondaire = eNivPrimaire
                                          );

   bool __fastcall ModifierModele(const AnsiString &aLogiciel,
                                  const AnsiString &aCategorie,
                                  const AnsiString &aCategorieVariables,
                                  const AnsiString &aLibelle,
                                  IDLangue eLangue,
                                  IDOrientation eOrientation,
                                  bool bGererEnTeteEtPiedDePage,
                                  const AnsiString &aRepSecondaire = EmptyStr,
                                  eNivModele eNoModeleSecondaire = eNivPrimaire,
                                  const TContrainteTaille *sContrainteTaille = NULL
                                  );

   void __fastcall SupprimerModelesSecondaire(const AnsiString &aLogiciel,
                                              const AnsiString &aCategorie,
                                              const AnsiString &aLibelle,
                                              IDLangue eLangue,
                                              IDOrientation eOrientation,
                                              const AnsiString &aRepSecondaire,
                                              eNivModele eNoModeleSecondaire
                                              );

   bool __fastcall TexteModeleExists(const AnsiString &aLogiciel,
                                     const AnsiString &aCategorie,
                                     const AnsiString &aLibelle,
                                     IDLangue eLangue,
                                     IDOrientation eOrientation);

  //Vérifie si le modèle aCourrier est référencé et l'ajoute s'il est absent.
  bool __fastcall VerifierCourrier(const AnsiString &aLogiciel,
                                   const AnsiString &aCategorie,
                                   const AnsiString &aCourrier,
                                   const AnsiString &aLibelle,
                                   IDLangue eLangue = lngFRANCAIS,
                                   IDOrientation eOrientation = eOrLibre,
                                   short shParam1 = 0,
                                   short shParam2 = 0);

  //Ajoute un modèle utilisateur
  bool __fastcall ImporterModele(const AnsiString &aFichier,
                                 bool bRemplacer,
                                 const AnsiString &aLogiciel,
                                 const AnsiString &aCategorie,
                                 const AnsiString &aLibelle,
                                 IDLangue eLangue = lngFRANCAIS,
                                 IDOrientation eOrientation = eOrLibre,
                                 short shParam1 = 0,
                                 short shParam2 = 0);

   bool __fastcall ImporterModeleSecondaire(const AnsiString &aFichier,
                                            bool bRemplacer,
                                            const AnsiString &aLogiciel,
                                            const AnsiString &aCategorie,
                                            const AnsiString &aLibelle,
                                            IDLangue eLangue,
                                            IDOrientation eOrientation,
                                            const AnsiString &aRepSecondaire,
                                            eNivModele eNoModeleSecondaire
                                            );

   //Installe un modèle livré
   bool __fastcall InstallerModele(const AnsiString &aFichier,
                                   const AnsiString &aLogiciel,
                                   const AnsiString &aCategorie,
                                   const AnsiString &aLibelle,
                                   IDLangue eLangue = lngFRANCAIS,
                                   IDOrientation eOrientation = eOrLibre,
                                   short shParam1 = 0,
                                   short shParam2 = 0);

  //Créer un modèle secondaire
  bool __fastcall CreerModeleSecondaire(const AnsiString &aLogiciel,
                                        const AnsiString &aCategorie,
                                        const AnsiString &aLibelle,
                                        IDLangue eLangue,
                                        IDOrientation eOrientation,
                                        const AnsiString &aRepSecondaire,
                                        eNivModele eNoModeleSource,
                                        eNivModele eNoModeleCible
                                        );

  //Renomme le modèle
  bool __fastcall RenommerModele(const AnsiString &aOldLogiciel,
                                 const AnsiString &aOldCategorie,
                                 const AnsiString &aOldLibelle,
                                 const AnsiString &aNewLogiciel,
                                 const AnsiString &aNewCategorie,
                                 const AnsiString &aNewLibelle);

  //Supprime le modèle (fichiers, enregistrements dans TableDoc, ListFich et CoordDoss)
  bool __fastcall SupprimerModele(const AnsiString &aLogiciel,
                                  const AnsiString &aCategorie,
                                  const AnsiString &aLibelle);

  //Vérifie si la variable aNom est référencée et l'ajoute si elle est absente.
  bool __fastcall VerifierVariable(const AnsiString &aLogiciel,
                                   const AnsiString &aCategorie,
                                   const AnsiString &aNom,
                                   const AnsiString &aLibelle,
                                   const AnsiString &aValeur = EmptyStr,
                                   bool bIsModifiableParUtilisateur = true);

  //Supprime la variable spécifiée
  bool __fastcall SupprimerVariable(const AnsiString &aLogiciel,
                                    const AnsiString &aCategorie,
                                    const AnsiString &aLibelle);

  //Initialise l'émetteur et les destinataires de chaques dossiers liés au
  //logiciel et à la catégorie.
  //Retourne le NoCoord lié à ce dossier
  unsigned long __fastcall InitEmetDest(const AnsiString &aLogiciel,
                                        const AnsiString &aCategorie,
                                        unsigned long NumEmet, TStringList *slDest,
                                        const AnsiString &aLibelle = EmptyStr,
                                        unsigned long NoCoord = 0);
  unsigned long __fastcall InitEmetDest(const AnsiString &aLogiciel,
                                        const AnsiString &aCategorie,
                                        unsigned long NumEmet, unsigned long NumDest,
                                        const AnsiString &aLibelle = EmptyStr,
                                        unsigned long NoCoord = 0);

  //Complète l'émetteur et les destinataires de chaques dossiers liés au
  //logiciel et à la catégorie s'ils sont absents.
  //Retourne le NoCoord lié à ce dossier
   unsigned long __fastcall CompleteEmetDest(const AnsiString &aLogiciel,
                                             const AnsiString &aCategorie,
                                             unsigned long NumEmet, TStringList *slDest,
                                             const AnsiString &aLibelle = EmptyStr,
                                             unsigned long NoCoord = 0);
   unsigned long __fastcall CompleteEmetDest(const AnsiString &aLogiciel,
                                             const AnsiString &aCategorie,
                                             unsigned long NumEmet, unsigned long NumDest,
                                             const AnsiString &aLibelle = EmptyStr,
                                             unsigned long NoCoord = 0);

   bool __fastcall GetListeEmetDest(const AnsiString &aLogiciel,
                                    const AnsiString &aCategorie,
                                    const AnsiString &aLibelle,
                                    unsigned long NoCoord,
                                    unsigned long *pNumEmet, TStringList *slDest
                                    );

   bool __fastcall DonneesSontTrouveesDansTable(TTypeTblCour eTypeTable,
                                                const AnsiString &aLogiciel);

   AnsiString __fastcall GetNomFichier(const AnsiString &aLogiciel,
                                       const AnsiString &aCategorie,
                                       const AnsiString &aLibelle,
                                       IDLangue eLangue,
                                       IDOrientation eOrientation,
                                       const AnsiString &aRepSecondaire = EmptyStr,
                                       eNivModele eNoModeleSecondaire = eNivPrimaire
                                       );

   bool GetInfosFichierModele(const AnsiString &aCourrier,
                              AnsiString *aLogiciel,
                              AnsiString *aCategorie,
                              AnsiString *aLibelle,
                              IDLangue *eLangue,
                              IDOrientation *eOrientation);

   // Informe l'éditeur de modèle que le modèle spécifié est utilisé par l'application. (Utilisé pour sauvegarder les modèles)
   // Une table "d'index" sera alors créé dans le répertoire aRepDossier
   /////////////////////////////////////////////////////////////////////////////
   void __fastcall SignalerUtilisationDuModele(short shIDUser,
                                               const AnsiString &aLogiciel,
                                               const AnsiString &aCategorie,
                                               const AnsiString &aLibelle,
                                               const AnsiString &aRepDossier);
   };
//---------------------------------------------------------------------------
#endif
